package ans1;

/**
 * @author Dujie
 * @create 2025/8/7
 * @since 1.0.0
 */
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.util.ASN1Dump;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class ASN1StreamExample {

    public static void main(String[] args) {
        try {
            // 1. 创建ASN.1数据结构并编码
            byte[] encodedData = createAndEncodeASN1Data();
            System.out.println("编码后的ASN.1数据 (HEX): " + bytesToHex(encodedData));

            // 2. 使用ASN1InputStream解码
            ASN1Primitive decodedObject = decodeWithASN1InputStream(encodedData);
            System.out.println("\n解码后的ASN.1对象结构:");
            System.out.println(ASN1Dump.dumpAsString(decodedObject, true));

            // 3. 使用ASN1OutputStream重新编码
            byte[] reencodedData = encodeWithASN1OutputStream(decodedObject);
            System.out.println("\n重新编码后的ASN.1数据 (HEX): " + bytesToHex(reencodedData));

            // 验证原始数据和重新编码数据是否相同
            System.out.println("\n原始编码与重新编码是否相同: " +
                    java.util.Arrays.equals(encodedData, reencodedData));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 创建并编码ASN.1数据结构
    private static byte[] createAndEncodeASN1Data() throws IOException {
        // 创建一个包含多种ASN.1类型的序列
        ASN1EncodableVector vector = new ASN1EncodableVector();
        vector.add(new ASN1Integer(1234567890L));          // INTEGER
        vector.add(new DERUTF8String("Hello ASN.1"));      // UTF8String
        vector.add(new DEROctetString(new byte[]{0x01, 0x02, 0x03})); // OCTET STRING

        // 创建一个嵌套的SEQUENCE
        ASN1EncodableVector nestedVector = new ASN1EncodableVector();
        nestedVector.add(ASN1Boolean.getInstance(true));           // BOOLEAN
        nestedVector.add(new ASN1ObjectIdentifier("1.2.840.113549.1.1.1")); // OID
        vector.add(new DERSequence(nestedVector));          // SEQUENCE

        // 创建顶级SEQUENCE
        DERSequence sequence = new DERSequence(vector);

        // 编码为字节数组
        return sequence.getEncoded();
    }

    // 使用ASN1InputStream解码
    private static ASN1Primitive decodeWithASN1InputStream(byte[] encodedData) throws IOException {
        ByteArrayInputStream bIn = new ByteArrayInputStream(encodedData);
        ASN1InputStream asn1In = new ASN1InputStream(bIn);

        try {
            // 读取ASN.1对象
            ASN1Primitive obj = asn1In.readObject();

            // 验证是否还有更多数据
            if (asn1In.readObject() != null) {
                throw new IOException("输入流中包含多个ASN.1对象");
            }

            return obj;
        } finally {
            asn1In.close();
        }
    }

    // 使用ASN1OutputStream编码
    private static byte[] encodeWithASN1OutputStream(ASN1Encodable asn1Object) throws IOException {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ASN1OutputStream asn1Out = ASN1OutputStream.create(bOut);

        try {
            // 写入ASN.1对象
            asn1Out.writeObject(asn1Object);
            asn1Out.flush();

            return bOut.toByteArray();
        } finally {
            asn1Out.close();
        }
    }

    // 辅助方法：字节数组转十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
}